<?php
/**
 * @author  Nam Nguyen <nam.ngvan@gmail.com>
 * @version 1.0
 * @since   Apr 19, 2013
 */
class Nuo_Filesystem
{

	/**
	 * @static
	 * @access  public
	 * @var  Nuo_Filesystem
	 */
	static private $_instance = null;

	/**
	 * Get file mime-type
	 * @access  public
	 * @param   string  $file
	 * @return  string
	 */
	public function getMimeType($file)
	{
		return 'image/jpg';
	}

	/**
	 * Get File extension
	 * @access  public
	 * @param   string $file
	 * @return  string
	 */
	public function getExtension($file)
	{
		if ($pos = strrpos($file, '.'))
		{
			return strtolower(substr($file, $pos + 1));
		}
		return '';
	}

	/**
	 * Get upload file info name.
	 * @access  public
	 * @param   string  $file
	 * @return  array
	 */
	public function getInfo($file)
	{
		return array(
			'tmp_name' => $file,
			'name' => basename($file),
			'type' => 'unknown/unknown', // @todo
			'size' => filesize($file)
		);
	}

	/**
	 * Create random path to storage data

	 * @access  public
	 * @param   string  $ext etc 'jpg'
	 * @return  string
	 */
	public function createPath($ext)
	{
		$ext = $ext ? strtolower('.' . $ext) : '';
		return date('Y/m/d') . get_random_text(6) . $ext;
	}

	/**
	 * Create random path to storage data
	 * @access  public
	 * @param   string  $ext etc 'jpg'
	 * @return  string
	 */
	public function createPathPattern($ext)
	{
		$ext = $ext ? strtolower('.' . $ext) : '';
		return date('Y/m/d/') . get_random_text(6) . '-{type}' . $ext;

	}

	/**
	 * Create random path to storage data
	 * @access  public
	 * @param string $ext
	 * @return string
	 */
	public function createTempPath($ext = '')
	{
		$ext = $ext ? strtolower('.' . $ext) : '';
		return PUBLIC_DIR . '/temp/' . get_random_text(16) . $ext;
	}

	/**
	 * Create random path to in temp path pattern
	 * @access  public
	 * @param   string  $ext
	 * @return  string
	 */
	public function createTempPathPattern($ext = '', $is_pattern = FALSE)
	{
		$ext = $ext ? strtolower('.' . $ext) : '';
		return PUBLIC_DIR . '/temp/' . get_random_text(16) . '-{type}' . $ext;
	}

	/**
	 * Make local directory
	 * @access  public
	 * @param string $path
	 * @param string $mode
	 * @return void
	 * @throws Exception
	 */
	public function makeDir($path, $mode = 0777)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Change perms
		$code = 0;
		if (is_dir($path))
		{
			@chmod($path, $mode);
		}
		else
		if (!@mkdir($path, $mode, true))
		{
			$code = 1;
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		// Respond
		if (1 == $code)
		{
			throw new Exception(strtr('Could not make dir "{path}"', array('{path}' => $path)));
		}
	}

	/**
	 * Make local file
	 * @access  public
	 * @param string $from
	 * @param string $to
	 * @return void
	 * @throws Exception
	 */
	public function moveFile($from, $to)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Move
		$code = 0;
		if (!is_file($from))
		{
			$code = 1;
		}
		else
		if (!@rename($from, $to))
		{
			@mkdir(dirname($to), 0777, true);
			if (!@rename($from, $to))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Exception(strtr('Could not move file "{from}" => "{to}"', array(
				'{from}' => $from,
				'{to}' => $to
			)));
		}
	}

	/**
	 * delete local file
	 * @access  public
	 * @param string $file
	 * @return void
	 * @throws Exception
	 */
	public function deleteFile($file)
	{
		// Delete
		$code = 0;
		if (is_file($file))
		{
			if (!@unlink($file))
			{
				@chmod($file, 0777);
				if (!@unlink($file))
				{
					$code = 1;
				}
			}
		}

		if (1 == $code)
		{
			throw new Exception(strtr('Could not delete file "{file}"', array('{file}' => $file)));
		}
	}

	/**
	 * copy local file
	 * @access  public
	 * @param string $from
	 * @param string $to
	 * @return TRUE
	 * @throws Exception
	 */
	public function copyFile($from, $to)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Copy
		$code = 0;
		if (!is_file($from))
		{
			$code = 1;
		}
		else
		if (!@copy($from, $to))
		{
			@mkdir(dirname($to), 0777, true);
			@chmod(dirname($to), 0777);
			if (!@copy($from, $to))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Exception(strtr('Could not to copy file "{from}" => "{to}"', array(
				'{from}' => $from,
				'{to}' => $to
			)));
		}
		return TRUE;
	}

	/**
	 * Write local file
	 * @access  public
	 * @param string $from
	 * @param string $data
	 * @return void
	 * @throws Exception
	 */
	public function writeFile($file, $data)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Write
		$code = 0;
		if (!@file_put_contents($file, $data))
		{
			if (is_file($file))
			{
				@chmod($file, 0666);
			}
			else
			if (is_dir(dirname($file)))
			{
				@chmod(dirname($file), 0777);
			}
			else
			{
				@mkdir(dirname($file), 0777, true);
			}

			if (!@file_put_contents($file, $data))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Exception(strtr('Unable to write to file "{file}"', array('{file}' => $file)));
		}
		return TRUE;
	}

	/**
	 * Copy local file
	 * @access  public
	 * @param string $file
	 * @return STRING
	 * @throws Exception
	 */
	public function readFile($file)
	{
		$content = NULL;

		if ($content = !@file_get_contents($file))
		{
			throw new Exception(strtr('Unable to read file "{file}"', array('{file}' => $file)));
		}
		return $content;
	}

	/**
	 * create random string
	 * @param int $len  default 16
	 * @return string
	 * It is generate random file name that companitible with Unix file name & window
	 * file name
	 * - include alpha num only
	 * - case in-sensitive ( it should not include special character)
	 * - lead by alphabelt
	 */
	public function getRandom($len)
	{

		$seek = 'qwertyuiopasdfghjklzxcvbnm';
		$max = strlen($seek) - 1;
		$ret = substr($seek, mt_rand(0, $max), 1);

		// fetch upload

		$seek = 'qwertyuiopasdfghjklzxcvbnm0123456789';
		$max = strlen($seek) - 1;
		for ($i = 1; $i < $len; ++$i)
		{
			$ret .= substr($seek, mt_rand(0, $max), 1);
		}

		return $ret;

	}

	/**
	 * @return array/NULL
	 */
	public function getUploads($field)
	{
		$files = isset($_FILES[$field]) ? $_FILES[$field] : NULL;

		if (!$files)
		{
			return NULL;
		}

		$return = NULL;

		if (is_string($files['tmp_name']))
		{
			$return = $files;
		}
		else
		if (is_array($files['tmp_name']))
		{
			foreach ($files['tmp_name'] as $index => $tmp_name)
			{
				if (empty($tmp_name))
				{

				}
				else
				if (is_string($tmp_name))
				{
					$size = $files['size'][$index];
					$error = $files['error'][$index];

					if (!$size or $error)
					{
						continue;
					}

					$return[$index] = array(
						'tmp_name' => $tmp_name,
						'size' => $size,
						'error' => $error,
						'name' => $files['name'][$index],
					);
				}
				else
				if (is_array($tmp_name))
				{
					foreach ($tmp_name as $index2 => $tmp_name2)
					{
						if (empty($tmp_name2))
						{

						}
						else
						{
							$size = $files['size'][$index][$index2];
							$error = $files['error'][$index][$index2];

							if (!$size or $error)
							{
								continue;
							}
							$return[] = array(
								'tmp_name' => $tmp_name2,
								'name' => $files['name'][$index][$index2],
								'size' => $size,
								'type' => $files['type'][$index][$index2],
								'error' => $error,
							);
						}

					}
				}
			}
		}
		else
		{
			throw new Exception("Invalid Upload Errors");
		}

		return $return;
	}

	/**
	 * @static
	 * @access  public
	 * @return  Nuo_Filesystem
	 */
	static function instance()
	{
		if (null == self::$_instance)
		{
			self::$_instance = new self;
		}
		return self::$_instance;
	}

}
